<?php

/**
 * This file is part of the Framework03 PHP framework.
 * @author Walter Tamboer
 * @package Framework03
 */

/**
 * The FW_Database_Adapter_Abstract is the base class for all database adapters that exist in the framework.
 */
abstract class FW_Database_Adapter_Abstract
{
    /**
     * @var array A list with parameters of this adapter.
     */
    private $parameters = array();

    /**
     * Initializes a new instance of this class.
     * @param array|FW_Config $options Optional options for this database adapter.
     */
    public function __construct($options = null)
    {
        $this->setOptions($options);
        $this->connect();
    }

    /**
     * Cleans up all the resources used by this class.
     */
    public function __destruct()
    {
        $this->disconnect();
    }

    /**
     * Sets the parameter with the given name.
     * @param string $name The name of the parameter to set.
     * @param mixed $value The value of the parameter to set.
     * @return FW_Database_Adapter_Abstract
     */
    public function setParameter($name, $value)
    {
        $this->parameters[$name] = $value;
        return $this;
    }

    /**
     * Gets the requested parameter.
     * @param string $name The name of the parameter to get.
     * @return mixed
     */
    public function getParameter($name)
    {
        if (!isset($this->parameters[$name]))
            throw new FW_Database_Adapter_Exception("Parameter $name not set.", 500);

        return $this->parameters[$name];
    }

    /**
     * Gets the host to connect to.
     * @return string
     */
    public function getHost()
    {
        return $this->getParameter('host');
    }

    /**
     * Gets the port to connect to.
     * @return int
     */
    public function getPort()
    {
        return $this->getParameter('port');
    }

    /**
     * Gets the username to login with.
     * @return string
     */
    public function getUsername()
    {
        return $this->getParameter('username');
    }

    /**
     * Gets the password to login with.
     * @return string
     */
    public function getPassword()
    {
        return $this->getParameter('password');
    }

    /**
     * Gets the name of the database to connect to.
     * @return string
     */
    public function getDatabaseName()
    {
        return $this->getParameter('dbname');
    }

    /**
     * Sets the options of this database adapter.
     * @param array|FW_Config $options Optional options for this database adapter.
     * return FW_Database_Adapter_Abstract
     */
    public function setOptions($options)
    {
        if (is_array($options))
        {
            foreach ($options as $name => $value)
                $this->setParameter($name, $value);
        }
        else if ($options instanceof FW_Config)
        {
            if ($options->contains('host'))
                $this->setParameter('host', $options->get('host'));

            if ($options->contains('port'))
                $this->setParameter('port', $options->get('port'));

            if ($options->contains('username'))
                $this->setParameter('username', $options->get('username'));

            if ($options->contains('password'))
                $this->setParameter('password', $options->get('password'));

            if ($options->contains('dbname'))
                $this->setParameter('dbname', $options->get('dbname'));
        }

        return $this;
    }

    /**
     * Creates a connection with the database.
     */
    abstract public function connect();

    /**
     * Destroys the current connection with the database.
     */
    abstract public function disconnect();

    /**
     * Executes the given database statement.
     * @param FW_Database_Statement_Abstract $statement
     * @return FW_Database_Adapter_Abstract|FW_Database_Adapter_Rowset
     */
    abstract public function execute(FW_Database_Statement_Abstract $statement);
}
